﻿using System;
using System.Linq;
using System.Security.Principal;
using System.Web;
using System.Web.Mvc;
using FormAuthentication.Practice.Areas.Admin.Models.SignIn;
using FormAuthentication.Practice.Areas.Customer.Controllers;
using FormAuthentication.Practice.Areas.Customer.Models.SignIn;

namespace FormAuthentication.Practice
{
    public class CustomizeAuthorizeAttribute: FilterAttribute, IAuthorizationFilter
    {
        private readonly string _customerArea;
        private readonly Func<ActionResult> _customerLogin;
        private readonly string _adminArea;
        private readonly Func<ActionResult> _adminLogin;

        public CustomizeAuthorizeAttribute(string customerArea,Func<ActionResult> customerLogin,string adminArea,Func<ActionResult> adminLogin)
        {
            _customerArea = customerArea;
            _customerLogin = customerLogin;
            _adminArea = adminArea;
            _adminLogin = adminLogin;
        }

        protected virtual bool AuthorizeCore(AuthorizationContext filterContext)
        {
            if (filterContext == null)
            {
                throw new ArgumentNullException("httpContext");
            }

            IPrincipal user = filterContext.HttpContext.User;
            if (!user.Identity.IsAuthenticated)
            {
                return false;
            }

            var customer = user as UserPrincipal;
            if (customer != null&&IsCustomerAreaRequest(filterContext))
            {
                return true;
            }

            var admin = user as AdminPrincipal;
            if (admin != null && IsAdminAreaRequest(filterContext))
            {
                return true;
            }

            return false;
        }

        public void OnAuthorization(AuthorizationContext filterContext)
        {
            if (filterContext == null)
            {
                throw new ArgumentNullException("filterContext");
            }


            bool skipAuthorization = filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), inherit: true)
                                     || filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), inherit: true);

            if (skipAuthorization)
            {
                return;
            }

            if (AuthorizeCore(filterContext))
            {
                HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache;
                cachePolicy.SetProxyMaxAge(new TimeSpan(0));
                cachePolicy.AddValidationCallback(CacheValidateHandler, null /* data */);
            }
            else
            {
                HandleUnauthorizedRequest(filterContext);
            }
        }

        private void CacheValidateHandler(HttpContext context, object data, ref HttpValidationStatus validationStatus)
        {
            //validationStatus = OnCacheAuthorization(new HttpContextWrapper(context));
        }

        private bool IsCustomerAreaRequest(AuthorizationContext filterContext)
        {
            var values = filterContext.RouteData.DataTokens.Values;
            if (values.ToList()[1].Equals(_customerArea))
            {
                return true;
            }

            return false;
        }

        private bool IsAdminAreaRequest(AuthorizationContext filterContext)
        {
            var values = filterContext.RouteData.DataTokens.Values;
            if (values.ToList()[1].Equals(_adminArea))
            {
                return true;
            }

            return false;
        }

        protected virtual void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            if (IsCustomerAreaRequest(filterContext))
            {
                //filterContext.Result = new HomeController().Login();
                filterContext.HttpContext.Response.Redirect("~/Customer/Home/Login");
            }
            else if (IsAdminAreaRequest(filterContext))
            {
                filterContext.Result = _adminLogin();
            }
            else
            {
                filterContext.Result = _adminLogin();
            }

        }

        //protected virtual HttpValidationStatus OnCacheAuthorization(HttpContextBase httpContext)
        //{
        //    if (httpContext == null)
        //    {
        //        throw new ArgumentNullException("httpContext");
        //    }

        //    bool isAuthorized = AuthorizeCore(httpContext);
        //    return (isAuthorized) ? HttpValidationStatus.Valid : HttpValidationStatus.IgnoreThisRequest;
        //}
    }
}